#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

#define SELF 1

namespace Protocol
{
    // 定义数据间的分隔符
    const std::string ProSep = " ";
    // 定义报文间的分隔符
    const std::string LineBreakSep = "\r\n";


    // "len\r\nx op y\r\n" : \r\n不属于报文的一部分，约定
    // "len\r\nresult code\r\n": \r\n不属于报文的一部分，约定
    // 添加报文间的分隔符
    std::string Encode(const std::string& message)
    {
        std::string len = std::to_string(message.size());
        return len + LineBreakSep + message + LineBreakSep;
    }


    // 删除报文间的分隔符，提取出一个报文
    bool Decode(std::string& package, std::string* message)
    {
        // 提取 len
        auto pos = package.find(LineBreakSep);
        if(pos == std::string::npos) return false;
        std::string len_str = package.substr(0, pos);
        int messageLen = std::stoi(len_str);

        int total = len_str.size() + messageLen + 2 * LineBreakSep.size();
        if(package.size() < total)  return false;

        // package内至少有一个完整的报文
        *message =  package.substr(pos + LineBreakSep.size(), messageLen);
        package.erase(0, total); // 提取出一个报文后，还需要从package中删除这个报文
        return true;
    }

    class Request
    {
    public:
        Request()
            : _data_x(0), _data_y(0), _oper(0)
        {
        }

        // 序列化：结构化数据->字符串 x op y
        bool Serialize(std::string *out)
        {
#ifdef SELF
            // 自定义序列化
            std::string x_str = std::to_string(_data_x);
            std::string y_str = std::to_string(_data_y);
            *out = x_str + ProSep + _oper + y_str;
            return true;
#else
            // 使用Json序列化
            Json::Value root;
            root["data_x"] = _data_x;
            root["data_y"] = _data_y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }

        // 反序列化：字符串->结构后数据
        bool Deserialize(const std::string &in)
        {
#ifdef SELF
            // 自定义反序列化     x op y
            auto leftSep = in.find(ProSep);
            if(leftSep == std::string::npos)  return false;
            auto rightSep = in.rfind(ProSep);
            if(rightSep == std::string::npos) return false;

            // 这里的1是oper的长度
            if(leftSep + ProSep.size() + 1 != rightSep) return false;

            std::string data_x = in.substr(0, leftSep);
            if(data_x.empty()) return false;
            std::string data_y = in.substr(rightSep + ProSep.size());
            if(data_y.empty()) return false;


            _data_x = std::stoi(data_x);        
            _data_y = std::stoi(data_y);        
            _oper = in[rightSep - 1];
            return true;
            // _oper = *in.substr(leftSep + ProSep.size(), rightSep).c_str();
#else
            // 使用Json反序列化
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if(res)
            {
                _data_x = root["data_x"].asInt();
                _data_y = root["data_y"].asInt();
                _oper = root["oper"].asInt();
            }    
            return res;
#endif
        }

        ~Request()
        {
        }

    private:
        int _data_x; // 第一个参数
        int _data_y; // 第二个参数
        char _oper;  // + - * / %
    };


    class Response
    {
    public:
        Response()
            : _result(0), _code(0)
        {
        }

        // 序列化：结构化数据->字符串 x op y
        bool Serialize(std::string *out)
        {
#ifdef SELF
            // 自定义序列化
            std::string result_str = std::to_string(_result);
            std::string code_str = std::to_string(_code);
            *out = result_str + ProSep + code_str;
            return true;
#else
            // 使用Json序列化
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }

        // 反序列化：字符串->结构后数据
        bool Deserialize(const std::string &in)
        {
#ifdef SELF
            // 自定义反序列化     result code
            auto Sep = in.find(ProSep);
            if(Sep == std::string::npos)  return false;

            std::string result = in.substr(0, Sep);
            if(result.empty()) return false;
            std::string code = in.substr(Sep + ProSep.size());
            if(code.empty()) return false;


            _result = std::stoi(result);        
            _code = std::stoi(code);    
            return true;    
#else
            // 使用Json反序列化
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if(res)
            {
                _result = root["result"].asInt();
                _code = root["code"].asInt();
            }    
            return res;
#endif
        }

        ~Response()
        {
        }

    private:
        int _result; // 结果
        int _code; // 有效位
    };


    // 简单的工厂模式，建造类设计模式
    class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req = std::make_shared<Request>();
            return req;
        }
        std::shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, op);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> resp = std::make_shared<Response>();
            return resp;
        }
        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            std::shared_ptr<Response> req = std::make_shared<Response>(result, code);
            return req;
        }
    };
}